﻿// =============================================
// 文件保护宏：防止该头文件被重复包含（避免编译错误）
// 如果尚未定义 CUSTOM_GI_INCLUDED，则定义它并继续，否则跳过该部分代码的编译
// =============================================
#ifndef CUSTOM_GI_INCLUDED
#define CUSTOM_GI_INCLUDED

// =============================================
// 引入 Unity 渲染管线核心库中关于实体光照（Entity Lighting）的工具函数
// 包括：SampleSingleLightmap、SampleSH9、SampleProbeVolumeSH4 等关键采样函数
// 这些函数用于从 Lightmap、SH 系数、Probe Volume 中提取间接光照信息
// =============================================
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl"

// =============================================
// 声明内置的 2D 纹理：unity_Lightmap
// 这是 Unity 默认的光照贴图（Lightmap）纹理，存储了烘焙好的间接漫反射光照信息
// 通常由 Unity Lightmapper 在烘焙阶段生成
// =============================================
TEXTURE2D(unity_Lightmap);
// 声明对应的采样器：samplerunity_Lightmap，用于从 lightmap 中安全采样
SAMPLER(samplerunity_Lightmap);

// =============================================
// 声明内置的 3D 纹理：unity_ProbeVolumeSH
// 用于存储 **Probe Volume 的球谐函数（SH）系数**，实现动态物体在探针体积内的间接光照
// 仅在启用了 Probe Volume 且使用相关设置时有效
// =============================================
TEXTURE3D_FLOAT(unity_ProbeVolumeSH);
// 对应的采样器
SAMPLER(samplerunity_ProbeVolumeSH);

// =============================================
// 条件编译：如果定义了 LIGHTMAP_ON（即当前物体使用了烘焙光照贴图）
// 则定义一系列与 Lightmap 相关的宏，用于标准化 Attribute、Varyings、数据传递
// =============================================
#if defined(LIGHTMAP_ON)
	// ======================
	// 定义 GI_ATTRIBUTE_DATA：在顶点输入结构体中添加 lightMapUV（TEXCOORD1）
	// 用于接收从 Mesh 中传递过来的 Lightmap UV 坐标
	// ======================
	#define GI_ATTRIBUTE_DATA float2 lightMapUV : TEXCOORD1;

	// ======================
	// 定义 GI_VARYINGS_DATA：在顶点输出 / 片段输入结构体中添加 lightMapUV（VAR_LIGHT_MAP_UV）
	// 用于将 Lightmap UV 从顶点传递到片段着色器
	// ======================
	#define GI_VARYINGS_DATA float2 lightMapUV : VAR_LIGHT_MAP_UV;

	// ======================
	// 定义 TRANSFER_GI_DATA：在顶点着色器中，将原始 lightMapUV 按照 unity_LightmapST（Tiling & Offset）进行变换
	// 得到最终用于采样的 UV 坐标，并赋值给输出结构体中的 lightMapUV
	// ======================
	#define TRANSFER_GI_DATA(input, output) \
		output.lightMapUV = input.lightMapUV * \
		unity_LightmapST.xy + unity_LightmapST.zw;

	// ======================
	// 定义 GI_FRAGMENT_DATA：在片段着色器中，直接返回传递过来的 lightMapUV，用于采样
	// ======================
	#define GI_FRAGMENT_DATA(input) input.lightMapUV

// =============================================
// 如果没有定义 LIGHTMAP_ON（即当前物体没有使用 Lightmap）
// 则定义一系列空的或无效的宏，表示不处理 Lightmap 相关数据
// =============================================
#else
	#define GI_ATTRIBUTE_DATA          // 顶点输入：无 Lightmap UV
	#define GI_VARYINGS_DATA           // 顶点输出：无 Lightmap UV
	#define TRANSFER_GI_DATA(input, output)  // 无数据传递
	#define GI_FRAGMENT_DATA(input) 0.0      // 片段中返回无效值
#endif

// =============================================
// 定义一个结构体：GI（Global Illumination）
// 用于封装所有间接光照相关的计算结果，目前只包含一个 diffuse（漫反射间接光）分量
// 可以后续扩展，比如加入 specular、ambient occlusion 等
// =============================================
struct GI {
	float3 diffuse; // 间接漫反射光照（环境光、烘焙光、SH 探针等）
};

// =============================================
// 函数：SampleLightMap
// 作用：如果启用了 LIGHTMAP_ON，则从 unity_Lightmap 中采样当前 UV 处的烘焙间接光照颜色
// 参数：
//   - lightMapUV：经过变换的 Lightmap UV 坐标
// 返回值：float3，采样到的间接光照颜色（通常是漫反射）
// 如果未启用 LIGHTMAP_ON，则返回 0.0（无光照）
// =============================================
float3 SampleLightMap(float2 lightMapUV) {
	#if defined(LIGHTMAP_ON)
  		// 调用 Unity 提供的 SampleSingleLightmap 函数，从 unity_Lightmap 纹理中采样
  		// 参数包括：纹理、采样器、UV、HDR 相关标志、亮度与曝光参数
  		return SampleSingleLightmap(
			TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), lightMapUV,
			float4(1.0, 1.0, 0.0, 0.0), // tiling / offset 一般为 (1,1,0,0)，也可自定义
			#if defined(UNITY_LIGHTMAP_FULL_HDR)
				false, // 是否为全 HDR 格式，通常为 false
			#else
				true,  // 是否对光照贴图做解码（伽马/线性空间转换等）
			#endif
			float4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0, 0.0) // HDR 参数
		);
	#else
		// 未启用 Lightmap，返回无光照
		return 0.0;
	#endif
}

// =============================================
// 函数：SampleLightProbe
// 作用：如果未使用 Lightmap，则尝试从 **光照探针（Light Probes）** 或 **Probe Volume** 中采样间接光照
// 参数：
//   - surfaceWS：世界空间中的表面信息（含 position、normal）
// 返回值：float3，采样到的间接光照颜色（来自 SH 或 Probe Volume）
// 如果启用了 LIGHTMAP_ON，则直接返回 0.0（优先使用 Lightmap）
// =============================================
float3 SampleLightProbe(Surface surfaceWS) {
	#if defined(LIGHTMAP_ON)
		// 如果启用了 Lightmap，就不使用 Light Probe，返回 0.0
		return 0.0;
	#else
		// 判断当前是否启用了 Probe Volume（unity_ProbeVolumeParams.x 为 1 表示启用）
		if (unity_ProbeVolumeParams.x) {
			// 如果启用了 Probe Volume，则调用 SampleProbeVolumeSH4 从 3D 纹理中采样 SH 系数
			return SampleProbeVolumeSH4(
				TEXTURE3D_ARGS(unity_ProbeVolumeSH, samplerunity_ProbeVolumeSH),
				surfaceWS.position,           // 世界空间位置
				surfaceWS.normal,             // 世界空间法线
				unity_ProbeVolumeWorldToObject, // 世界到物体的变换矩阵
				unity_ProbeVolumeParams.y,    // Probe Volume 参数
				unity_ProbeVolumeParams.z,    // Probe Volume 参数
				unity_ProbeVolumeMin.xyz,     // Probe Volume 的最小角点
				unity_ProbeVolumeSizeInv.xyz  // Probe Volume 的尺寸倒数
			);
		}
		else {
			// 如果没有启用 Probe Volume，则使用 Unity 默认的球谐光照（SH9）
			// 从内置的 SH 系数（unity_SHAr, ..., unity_SHC）中采样
			float4 coefficients[7];
			coefficients[0] = unity_SHAr;
			coefficients[1] = unity_SHAg;
			coefficients[2] = unity_SHAb;
			coefficients[3] = unity_SHBr;
			coefficients[4] = unity_SHBg;
			coefficients[5] = unity_SHBb;
			coefficients[6] = unity_SHC;
			// 调用 SampleSH9，根据法线计算间接漫反射光照
			return max(0.0, SampleSH9(coefficients, surfaceWS.normal));
		}
	#endif
}

// =============================================
// 函数：GetGI
// 作用：整合 **光照贴图（Lightmap）** 和 **光照探针（SH / Probe Volume）** 的采样结果，
// 得到一个完整的 GI（全局间接光照）结构体，主要提供 diffuse（漫反射间接光）信息
// 参数：
//   - lightMapUV：经过变换的 Lightmap UV 坐标
//   - surfaceWS：世界空间表面信息（含 position、normal）
// 返回值：GI 结构体，包含间接漫反射颜色
// =============================================
GI GetGI(float2 lightMapUV, Surface surfaceWS) {
	GI gi;
	// 间接光照的漫反射部分 = 光照贴图采样结果 + 光照探针采样结果
	gi.diffuse = SampleLightMap(lightMapUV) + SampleLightProbe(surfaceWS);
	return gi;
}

// =============================================
// 文件保护宏结束
// =============================================
#endif